<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>Mali OpenCL SDK v1.1.0: Memory Buffers</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">Mali OpenCL SDK v1.1.0
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.2 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Home</span></a></li>
      <li class="current"><a href="pages.html"><span>Help&#160;and&#160;Tutorials</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('memory_buffers_tutorial.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Memory Buffers </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>How to share of memory efficiently between a Mali-T600 series GPU and a CPU.</p>
<h1><a class="anchor" id="memoryBuffersIntroduction"></a>
Introduction</h1>
<p>When dealing with large amounts of data (as is typically the case in OpenCL applications) it is important to ensure that transfer of that memory between the host and the OpencL device is as efficient as possible.</p>
<p>We have already seen how to use memory buffers in the <a class="el" href="hello_world_tutorial.html">Hello World</a> tutorial. The Hello World tutorial follows what we consider "best practices" for data sharing between the host and an OpenCL device. This tutorial explains those best practises.</p>
<p>Unless otherwise noted, all code snippets come from <a class="el" href="hello__world__vector_8cpp.html">hello_world_vector.cpp</a>.</p>
<h1><a class="anchor" id="memoryBufferssharedMemorySystems"></a>
Shared Memory Systems</h1>
<p>OpenCL is typically run on systems where the application processor and the GPU have separate memories. To share data between the GPU and CPU on these systems you must allocate buffers and copy data to and from the separate memories.</p>
<p>Systems with Mali GPUs typically have a shared memory so you are not required to copy data. However, OpenCL assumes the memories are separated and buffer allocation involves memory copies. This is wasteful because copies take time and consume power.</p>
<h1><a class="anchor" id="memoryBuffersAcrossDevices"></a>
Sharing Data Across Devices</h1>
<p>To avoid the copies, use the OpenCL API to allocate memory buffers and use mapping operations. These operations enable both the application processor and the Mali GPU to access the data without any copying.</p>
<dl class="section note"><dt>Note</dt><dd>OpenCL must be initialised before allocating memory buffers.</dd></dl>
<ol type="1">
<li><p class="startli"><b>Allocating memory buffers</b></p>
<p class="startli">The application creates buffer objects that can pass data to and from the kernels by calling clCreateBuffer(). All memory allocated on a shared memory system is physically accessible by both CPU and GPU cores. However, only memory that is allocated by clCreateBuffer is mapped into both the CPU and GPU virtual memory spaces. So memory allocated using malloc(), etc, is only mapped onto the CPU (image 1).</p>
<div class="image">
<img src="memory_malloc.png" alt="memory_malloc.png"/>
<div class="caption">
Image 1: Buffers created by user (malloc) are not mapped into the GPU memory space</div></div>
<p> So calling clCreateBuffer() with <b>CL_MEM_USE_HOST_PTR</b> and passing in a user created buffer requires the driver to create a new buffer and copy the data (identical to <b>CL_MEM_COPY_HOST_PTR</b>). This copy reduces performance (image 2).</p>
<div class="image">
<img src="use_host_ptr.png" alt="use_host_ptr.png"/>
<div class="caption">
Image 2: clCreateBuffer(CL_MEM_USE_HOST_PTR) creates a new buffer and copies the data over (but the copy operations are expensive)</div></div>
<p> <br/>
 So where possible always use <b>CL_MEM_ALLOC_HOST_PTR</b>. This allocates memory that both CPU and GPU can use without a copy (image 3).</p>
<div class="fragment"><div class="line">    memoryObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &amp;errorNumber);</div>
<div class="line">    createMemoryObjectsSuccess &amp;= <a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(errorNumber);</div>
<div class="line"></div>
<div class="line">    memoryObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &amp;errorNumber);</div>
<div class="line">    createMemoryObjectsSuccess &amp;= <a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(errorNumber);</div>
<div class="line"></div>
<div class="line">    memoryObjects[2] = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &amp;errorNumber);</div>
<div class="line">    createMemoryObjectsSuccess &amp;= <a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(errorNumber);</div>
</div><!-- fragment --><p> <br/>
 </p>
<div class="image">
<img src="alloc_host_ptr.png" alt="alloc_host_ptr.png"/>
<div class="caption">
Image 3: clCreateBuffer(CL_MEM_ALLOC_HOST_PTR) creates a buffer visible by both GPU and CPU</div></div>
</li>
<li><p class="startli"><b>Map memory objects</b></p>
<p class="startli">As mentioned before, we map the memory buffers created by the OpenCL implementation to pointers so we can access them on the CPU. </p>
<div class="fragment"><div class="line">    cl_int* inputA = (cl_int*)clEnqueueMapBuffer(commandQueue, memoryObjects[0], CL_TRUE, CL_MAP_WRITE, 0, bufferSize, 0, NULL, NULL, &amp;errorNumber);</div>
<div class="line">    mapMemoryObjectsSuccess &amp;= <a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(errorNumber);</div>
<div class="line"></div>
<div class="line">    cl_int* inputB = (cl_int*)clEnqueueMapBuffer(commandQueue, memoryObjects[1], CL_TRUE, CL_MAP_WRITE, 0, bufferSize, 0, NULL, NULL, &amp;errorNumber);</div>
<div class="line">    mapMemoryObjectsSuccess &amp;= <a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(errorNumber);</div>
</div><!-- fragment --></li>
<li><p class="startli"><b>Initialize data using the C pointers</b></p>
<p class="startli">Once the buffers have been mapped to a <em>cl_int</em> pointer, they can be used as a normal C pointer to initialize the data. </p>
<div class="fragment"><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; arraySize; i++)</div>
<div class="line">    {</div>
<div class="line">       inputA[i] = i;</div>
<div class="line">       inputB[i] = i;</div>
<div class="line">    }</div>
</div><!-- fragment --></li>
<li><p class="startli"><b>Unmap memory objects</b></p>
<p class="startli">When we are finished using the memory objects, we unmap them from the CPU side. We unmap the memory because otherwise:</p>
<ul>
<li>Reads and writes to that memory from inside a kernel on the OpenCL side are undefined,</li>
<li>The OpenCL implementation cannot free the memory when it is finished. <div class="fragment"><div class="line">    <span class="keywordflow">if</span> (!<a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(clEnqueueUnmapMemObject(commandQueue, memoryObjects[0], inputA, 0, NULL, NULL)))</div>
<div class="line">    {</div>
<div class="line">       <a class="code" href="common_8cpp.html#acd459e74d0cef3c4616c7ce1a5a47f4d" title="Release any OpenCL objects that have been created.">cleanUpOpenCL</a>(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);</div>
<div class="line">       cerr &lt;&lt; <span class="stringliteral">&quot;Unmapping memory objects failed &quot;</span> &lt;&lt; __FILE__ &lt;&lt; <span class="stringliteral">&quot;:&quot;</span>&lt;&lt; __LINE__ &lt;&lt; endl;</div>
<div class="line">       <span class="keywordflow">return</span> 1;</div>
<div class="line">    }</div>
<div class="line"></div>
<div class="line">    <span class="keywordflow">if</span> (!<a class="code" href="common_8cpp.html#a73727ed6f5d821d8c97756404e145644" title="Check an OpenCL error number for errors.">checkSuccess</a>(clEnqueueUnmapMemObject(commandQueue, memoryObjects[1], inputB, 0, NULL, NULL)))</div>
<div class="line">    {</div>
<div class="line">       <a class="code" href="common_8cpp.html#acd459e74d0cef3c4616c7ce1a5a47f4d" title="Release any OpenCL objects that have been created.">cleanUpOpenCL</a>(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);</div>
<div class="line">       cerr &lt;&lt; <span class="stringliteral">&quot;Unmapping memory objects failed &quot;</span> &lt;&lt; __FILE__ &lt;&lt; <span class="stringliteral">&quot;:&quot;</span>&lt;&lt; __LINE__ &lt;&lt; endl;</div>
<div class="line">       <span class="keywordflow">return</span> 1;</div>
<div class="line">    }</div>
</div><!-- fragment --> </li>
</ul>
</li>
</ol>
<h1><a class="anchor" id="memoryBuffersRecommendations"></a>
Additional Recommendations</h1>
<p>In addition to the above tutorial, we recommend the following:</p>
<ul>
<li>Do not use private or local memory. There is no performance gain using these on the Mali-T600 Series GPUs.</li>
<li>In the event that your kernels are memory bandwidth limited, use a formula to compute variables instead of reading from memory.</li>
</ul>
<h1><a class="anchor" id="memoryBuffersMoreInformation"></a>
More Information</h1>
<p>For more information have a look at the <a class="el" href="hello_world_tutorial.html">Hello World</a> tutorial.</p>
<p>Find solutions for <a class="el" href="common_issues.html">Common Issues</a>. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="tutorials.html">Tutorials</a></li>
    <li class="footer">
        <a href="http://www.arm.com/">(C) ARM Ltd. 2013</a>
    </li>
  </ul>
</div>
</body>
</html>
